<script setup lang="ts">
import { onHide, onLoad, onShow } from '@dcloudio/uni-app'
import {computed, reactive, ref} from 'vue'
import { getStatus, switchTabBarTheme } from '@/utils/common'
import {AuthStatus, DriverStatus, Status} from '@/types/constants'
import { getDriverAuthStatusAPI } from '@/api/user'
import {useToast} from "wot-design-uni"
import type {OrderGrabInfoVO, RoutePlanningDTO} from "@/types/order"
import useTokenStore from '@/stores/token'
import useCityCodeStore from '@/stores/cityCode'
import useDriverIdStore from '@/stores/driverId'
import type {DriverLocationDTO} from "@/types/map"
import { deleteDriverLocationAPI, updateDriverLocationAPI } from "@/api/map"
import {grabOrderAPI} from "@/api/order";

const toast = useToast()
const { setCityCode } = useCityCodeStore()
const { driverId, setDriverId } = useDriverIdStore()
const initDriverId = ref(driverId)
let screenHeight = ref<number>()
const role = ref(Status.NOT_LOGIN)
const key = import.meta.env.VITE_MAP_KEY
const location = reactive<{ startLocation: string, endLocation: string } & RoutePlanningDTO>({
  startLocation: '从哪儿出发',
  endLocation: '你要去哪儿',
  startLongitude: 116.397505,
  startLatitude: 39.908675,
  endLongitude: 0,
  endLatitude: 0
})
const markers = reactive([
  {
    id: 1,
    latitude: location.startLatitude,
    longitude: location.startLongitude,
    iconPath: '../../static/images/location.png',
    width: 40,
    height: 40,
  },
])
const driverLocationDTO = reactive<DriverLocationDTO>({
  cityCode: '',
  longitude: location.startLongitude,
  latitude: location.startLatitude,
  driverInfo: {
    driverId: 0,
    driverStatus: DriverStatus.IDLE
  }
})
onLoad(() => {
  switchTabBarTheme()
  role.value = getStatus()
  screenHeight.value = 2 * uni.getSystemInfoSync().windowHeight
  uni.getLocation({
    type: 'gcj02',
    isHighAccuracy: true,
    success: res => {
      location.startLatitude = res.latitude
      location.startLongitude = res.longitude
      markers[0].latitude = location.startLatitude
      markers[0].longitude = location.startLongitude
      uni.request({
        url: 'https://apis.map.qq.com/ws/geocoder/v1/?location=' + location.startLatitude + ',' + location.startLongitude + '&key=' + key,
        method: 'GET',
        success: result => {
          const data = result.data as any
          const cityCode = data.result.ad_info.adcode.slice(0, 4)
          setCityCode(cityCode)
          driverLocationDTO.cityCode = cityCode
          location.startLocation = data.result.formatted_addresses.recommend
        }
      })
      if (role.value !== Status.DRIVER) {
        const map = uni.createMapContext('map')
        map.addMarkers({ markers: markers, clear: true })
      }
    },
    fail: () => {
      toast.show('获取位置失败，请开启定位')
    }
  })
})

const choosePlace = requirePlugin('chooseLocation')
const isOptStart = ref<boolean>(true)
onShow(() => {
  const place = choosePlace.getLocation()
  if (place) {
    if (isOptStart.value) {
      location.startLocation = place.name
      location.startLatitude = place.latitude
      location.startLongitude = place.longitude
      markers[0].latitude = location.startLatitude
      markers[0].longitude = location.startLongitude
      const map = uni.createMapContext('map')
      map.addMarkers({ markers: markers, clear: true })
    }
    else {
      location.endLocation = place.name
      location.endLatitude = place.latitude
      location.endLongitude = place.longitude
      uni.navigateTo({ url: '/pages/index/orderRoute?locationDTO=' + JSON.stringify(location) })
    }
  }
  else {
    location.endLocation = '你要去哪儿'
    location.endLatitude = 0
    location.endLongitude = 0
  }
})

const isLogin = () => {
  if (role.value === Status.NOT_LOGIN) uni.navigateTo({ url: '/pages/login/index' })
}
const receiveCoupon = () => {
  isLogin()
  uni.navigateTo({ url: '/pages/index/receiveCoupon' })
}
const choosePoint = () => {
  uni.navigateTo({
    url: 'plugin://chooseLocation/index?key=' + key + '&referer=地图选点' + '&location=' +
        JSON.stringify({ latitude: location.startLatitude, longitude: location.startLongitude })
  })
}
const chooseStartPoint = () => {
  isLogin()
  isOptStart.value = true
  choosePoint()
}
const chooseEndPoint = () => {
  isLogin()
  isOptStart.value = false
  choosePoint()
}

const time = ref<number>(0)
const formatTime = computed(() => `${String(Math.floor(time.value / 60)).padStart(2, '0')}:${String(time.value % 60).padStart(2, '0')}`)
const timer = ref<number | undefined>()
const uploadTimer = ref<number | undefined>()
const isAuth = ref(false)
const { token } = useTokenStore()
const url: string = import.meta.env.VITE_API_URL
const socketTask = ref<UniNamespace.SocketTask | null>(null)
const orderGrabInfoVO = reactive<OrderGrabInfoVO>({
  id: 0,
  driverId: 0,
  startLocation: '',
  endLocation: '',
  estimateDistance: '0',
  estimateDuration: '0',
  estimateIncome: '0',
  nearbyDistance: '0'
})
const showOrder = ref<boolean>(false)
const uploadDriverLocation = (driverStatus: DriverStatus) => {
  uni.getLocation({
    type: 'gcj02',
    isHighAccuracy: true,
    success: res => {
      driverLocationDTO.latitude = res.latitude
      driverLocationDTO.longitude = res.longitude
    },
    fail: () => {
      toast.show('获取位置失败，请开启定位')
    }
  })
  driverLocationDTO.driverInfo.driverStatus = driverStatus
  updateDriverLocationAPI(driverLocationDTO)
}
const receiveOrder = async () => {
  isLogin()
  if (timer.value) {
    // 取消接单
    if (socketTask.value) socketTask.value.close({})
    await deleteDriverLocationAPI(driverLocationDTO.cityCode, driverLocationDTO.driverInfo.driverId)
    clearInterval(timer.value)
    clearInterval(uploadTimer.value)
    timer.value = undefined
    uploadTimer.value = undefined
    showOrder.value = false
  }
  else {
    // 开始接单
    if (!isAuth.value) {
      // 未认证
      const res = await getDriverAuthStatusAPI()
      if (res.data.authStatus !== AuthStatus.ALREADY_AUTH) await uni.navigateTo({ url: '/pages/index/authorize?authStatus=' + res.data })
      isAuth.value = true
      const driverId = res.data.driverId as number
      setDriverId(driverId)
      initDriverId.value = driverId
      driverLocationDTO.driverInfo.driverId = driverId
    }
    time.value = 0
    timer.value = setInterval(() => {
      time.value++
    }, 1000)
    uploadDriverLocation(DriverStatus.IDLE)
    uploadTimer.value = setInterval(() => {
      uploadDriverLocation(DriverStatus.IDLE)
    }, 10000)
    socketTask.value = uni.connectSocket({
      url: 'ws://'+ url.substring(url.indexOf("//") + 2) +'/order/ws/driver/' + initDriverId.value,
      header: {  'Authorization': 'Bearer ' + token },
      complete: () => {}
    })
    socketTask.value.onMessage(res => {
      const data = JSON.parse(res.data) as OrderGrabInfoVO
      if (data.driverId === initDriverId.value) {
        Object.assign(orderGrabInfoVO, data)
        showOrder.value = true
      }
    })
  }
}

const grabOrder = async (id: number) => {
  const res = await grabOrderAPI({ id: id, driverId: orderGrabInfoVO.driverId, estimateIncome: orderGrabInfoVO.estimateIncome })
  if (res.code === 200) {
    clearInterval(timer.value)
    clearInterval(uploadTimer.value)
    timer.value = undefined
    uploadTimer.value = undefined
    showOrder.value = false
    await uni.navigateTo({ url: '/pages/index/orderRoute?orderId=' + id })
  }
  else {
    toast.show(res.msg)
    showOrder.value = false
  }
}

onHide(() => {
  choosePlace.setLocation(null)
  clearInterval(timer.value)
  clearInterval(uploadTimer.value)
  timer.value = undefined
  uploadTimer.value = undefined
  showOrder.value = false
  if (socketTask.value) socketTask.value.close({})
})
</script>

<template>
  <wd-toast />
  <view :style="{ height: screenHeight + 'rpx' }">
    <map
      id="map" style="width: 100%; height: 100%" :show-location="true"
      :latitude="location.startLatitude" :longitude="location.startLongitude"
    />
    <view v-show="showOrder">
      <view class="top">
        <view class="info">
          <view class="item">
            <view>起点：</view>
            <wd-text :text="orderGrabInfoVO.startLocation" :lines="1" />
          </view>
          <view class="item">
            <view>终点：</view>
            <wd-text :text="orderGrabInfoVO.endLocation" :lines="1" />
          </view>
          <view class="item">
            <view class="left">
              <view>路线距离：</view>
              <view>{{ orderGrabInfoVO.estimateDistance }}公里</view>
            </view>
            <view class="right">
              <view>路线用时：</view>
              <view>{{ orderGrabInfoVO.estimateDuration }}分钟</view>
            </view>
          </view>
          <view class="item">
            <view class="left">
              <view>预估收入：</view>
              <view>{{ orderGrabInfoVO.estimateIncome }}元</view>
            </view>
            <view class="right">
              <view>距离你{{ parseFloat(orderGrabInfoVO.nearbyDistance) > 1 ? parseFloat(orderGrabInfoVO.nearbyDistance).toFixed(1) + '公里' : 100 * parseFloat(orderGrabInfoVO.nearbyDistance) + '米' }}</view>
            </view>
          </view>
        </view>
        <view class="button">
          <wd-button @click="grabOrder(orderGrabInfoVO.id)" block custom-style="margin-top: 20rpx;">立即抢单</wd-button>
        </view>
      </view>
    </view>
    <view v-if="role === Status.DRIVER" class="footer-driver">
      <wd-button
        @click="receiveOrder"
        custom-style="width: 90%; background-color: #2796f2;"
        size="large"
        >{{ timer ? formatTime + ' 取消' : '开始接单' }}</wd-button
      >
    </view>
    <view v-else class="footer">
      <img @click="receiveCoupon" class="coupon" src="@/static/images/coupon.jpg" alt="" />
      <view class="address">
        <view @click="chooseStartPoint" class="start-point">
          <view class="dot green"></view>
          <wd-text custom-style="width: 68%;" :text="location.startLocation" :lines="1" color="green" />
          <wd-text custom-class="custom-class" custom-style="width: 10%;" text="上车" />
          <wd-icon name="arrow-right" size="40rpx"></wd-icon>
        </view>
        <view @click="chooseEndPoint" class="end-point">
          <view class="dot red"></view>
          <wd-text custom-style="width: 68%" :text="location.endLocation" :lines="1" custom-class="custom-class" />
        </view>
      </view>
    </view>
  </view>
</template>

<style scoped lang="scss">
.top {
  width: 80%;
  height: 320rpx;
  margin-left: 5%;
  background-color: var(--front-color);
  position: fixed;
  top: 160rpx;
  display: flex;
  flex-direction: column;
  padding: 20rpx 5%;
  border-radius: 20rpx;
  .info {
    flex: 4;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    .item {
      display: flex;
      .left {
        flex: 1;
        display: flex;
      }
      .right {
        flex: 1;
        display: flex;
      }
    }
  }
  .button {
    flex: 2;
  }
}
.footer-driver {
  position: fixed;
  width: 96%;
  height: 150rpx;
  bottom: 60rpx;
  background-color: var(--back-color);
  margin-left: 2%;
  border-radius: 40rpx;
  display: flex;
  justify-content: center;
  align-items: center;
}
.footer {
  position: fixed;
  border-radius: 60rpx;
  bottom: 40rpx;
  width: 100%;
  height: 340rpx;
  background-color: #f7f7f7;
  .coupon {
    width: 100%;
    height: 63%;
    border-top-left-radius: 60rpx;
    border-top-right-radius: 60rpx;
  }
  .address {
    position: absolute;
    display: flex;
    flex-direction: column;
    align-items: center;
    border-radius: 40rpx;
    width: 96%;
    height: 62%;
    margin-left: 2%;
    bottom: 0;
    padding: 10rpx 0;
    background-color: var(--front-color);
    :deep(.custom-class) {
      color: var(--color);
    }
    .start-point,
    .end-point {
      display: flex;
      align-items: center;
      flex: 1;
      width: 95%;
    }
    .dot {
      width: 20rpx;
      height: 20rpx;
      border-radius: 50%;
      margin-left: 30rpx;
      margin-right: 30rpx;
    }
    .start-point {
      .green {
        background-color: #0f0;
      }
    }
    .end-point {
      border-radius: 40rpx;
      background-color: var(--front-color1);
      .red {
        background-color: #f00;
      }
    }
  }
}
</style>